//`timescale 1ns/1ps
module top_testbench();
				//clock and reset
	wire			gclk_tmr3;
	wire			reset_n;
				//inputs
	wire			bus_tmr3_sel;
	wire			bus_tmr3_we;
	wire	[3:0]	bus_addr;
	wire	[7:0]	bus_wdata;
	reg				tmr3_cnt_ev;
	reg				tmr3_cap_ev;
	reg				int_tmr_cnt_we;
	reg				int_tmr_cnt_wdata;
	reg				int_cap_cmp_we;
	reg 			int_cap_cmp_wdata;
				//outputs
	wire			tmr3_int;
	wire			tmr3_cap_cmp_int;
	wire			tmr3_on;
	wire			tmr3_cmp_out;
	wire	[7:0]	tmr3_rdata;
	wire			clk;
Generator_gclk_tmr3_reset inst_Generator_gclk_tmr3_reset(
				.gclk_tmr3(gclk_tmr3),
				.reset_n(reset_n),
				.tmr3_clk_en(tmr3_clk_en),
				.clk(clk)
				);
cpu_model cpu( 
				.clk(clk),
				.reset_n(reset_n),
				//inputs
				.bus_tmr3_sel(bus_tmr3_sel),
				.bus_tmr3_we(bus_tmr3_we),
				.bus_addr(bus_addr),
				.bus_wdata(bus_wdata),
				//outputs
				.tmr3_int(tmr3_int),
				.tmr3_cap_cmp_int(tmr3_cap_cmp_int),
				.tmr3_rdata(tmr3_rdata)
				);	

tmr3_top DUT_IP	(
				//clock and reset
				.gclk_tmr3(gclk_tmr3),
				.reset_n(reset_n),
				//inputs
				.bus_tmr3_sel(bus_tmr3_sel),
				.bus_tmr3_we(bus_tmr3_we),
				.bus_addr(bus_addr),
				.bus_wdata(bus_wdata),
				.tmr3_cnt_ev(tmr3_cnt_ev),
				.tmr3_cap_ev(tmr3_cap_ev),
				.int_tmr_cnt_we(int_tmr_cnt_we),
				.int_tmr_cnt_wdata(int_tmr_cnt_wdata),
				.int_cap_cmp_we(int_cap_cmp_we),
				.int_cap_cmp_wdata(int_cap_cmp_wdata),
				//outputs
				.tmr3_int(tmr3_int),
				.tmr3_cap_cmp_int(tmr3_cap_cmp_int),
				.tmr3_clk_en(tmr3_clk_en),
				.tmr3_cmp_out(tmr3_cmp_out),
				.tmr3_rdata(tmr3_rdata)
				);
initial begin
	inst_Generator_gclk_tmr3_reset.Generator_reset(100);
	fork
	//		tc2;
	//#400	tc3;
	//#1000	tc4;
	//#2000	tc5;
	//#4000 tc6;
			tc16;
	join
end
reg [7:0] data_tcon;
reg [5:0] data_sca;

parameter 	data_init_u = 8'hff,
			data_init_h = 8'hff,
			data_init_l = 8'hf5;
//Initial for all input reset
initial begin
	int_tmr_cnt_we = 1'b0;
	int_cap_cmp_we = 1'b0;
end
integer i,j,a,b;
initial begin
	a = 40;
	b = 30;
for ( i = 0; i < 10; i = i + 1) begin
	for ( j = 0; j < 10; j = j + 1) begin
		a = a + j;
		b = b + j;
		#a
		tmr3_cnt_ev = 1;
		tmr3_cap_ev = 1;
		#b
		tmr3_cnt_ev = 0;
		tmr3_cap_ev = 0;
	end
end
end 

task tc1;
	begin
		data_tcon[5:0] = $random;
		
		data_tcon = {1'b0,1'b0,data_tcon[5:1]};
		cpu.MOVT (4'b0001,$random);
		cpu.MOVT (4'b0000,data_tcon);
	end
endtask
	
task tc2;
	begin
		data_tcon[5:0] = $random;
		data_sca[5:2] = 4'b0000;
		
		data_sca = {data_sca[5:2],2'b00};
		cpu.MOVT (4'b0001,data_sca);
		data_tcon = {1'b1,1'b0,data_tcon[5:0]};
		cpu.MOVT (4'b0000,data_tcon);

	end
endtask

task tc3;
	begin
		data_tcon[5:1] = $random;
		data_sca[5:2] = 4'b0000;
		
		data_sca = {data_sca[5:2],2'b01};
		cpu.MOVT (4'b0001,data_sca);
		data_tcon = {1'b1,1'b0,data_tcon[5:1],1'b0};
		cpu.MOVT (4'b0000,data_tcon);
	end
endtask	

task tc4;
	begin
		data_tcon[5:0] = $random;
		data_sca[5:2] = $random;

		data_sca = {data_sca[5:2],2'b10};
		cpu.MOVT (4'b0001,data_sca);
		data_tcon = {1'b1,1'b0,data_tcon[5:0]};
		cpu.MOVT (4'b0000,data_tcon);
	end
endtask	

task tc5;
	begin
		data_tcon[5:0] = $random;
		data_sca[5:2] = $random;
		
		data_sca = {data_sca[5:2],2'b11};
		cpu.MOVT (4'b0001,data_sca);
		data_tcon = {1'b1,1'b0,data_tcon[5:0]};
		cpu.MOVT (4'b0000,data_tcon);
	end
endtask	

task tc6;
	begin
		data_tcon[5:0] = $random;
		data_sca[5:2] = $random;
		
		data_sca = {data_sca[5:2],2'b10};
		cpu.MOVT (4'b0001,data_sca);
		data_tcon = {1'b1,1'b0,data_tcon[5:0]};
		cpu.MOVT (4'b0000,data_tcon);
		#400
		tc1;
	end
endtask

task tc7;
	begin
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h); 
		cpu.MOVT (4'b0010, data_init_l);
		tc2;
	end
endtask

task tc8;
	begin
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h); 
		cpu.MOVT (4'b0010, data_init_l);
		tc3;
	end
endtask

task tc9;
	begin
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h); 
		cpu.MOVT (4'b0010, data_init_l);
		tc4;
	end
endtask

task tc10;
	begin
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h); 
		cpu.MOVT (4'b0010, data_init_l);
		tc5;
	end
endtask

task tc11;
	begin
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h); 
		cpu.MOVT (4'b0010, data_init_l);
		tc1;
	end
endtask

task tc12;
	begin
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h); 
		cpu.MOVT (4'b0010, data_init_l);
		tc3;
		#2000
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h); 
		cpu.MOVT (4'b0010, 8'hfa);
	end
endtask

task tc13;
	begin
		tc7;
		cpu.MOVT (4'b0001, 8'b0000_00);
	end
endtask

task tc14;
	begin
		tc8;
		cpu.MOVT (4'b0001, 8'b0000_01);		
	end
endtask

task tc15;
	begin
		tc12;
		cpu.MOVT (4'b0001, 8'b0001_00);		
	end
endtask
//timer
task tc16;
	begin
		tc12;
		#500
		data_tcon[5:1] = $random; 
		data_tcon = {1'b0,1'b0,data_tcon[5:1],1'b0};
		cpu.MOVT (4'b0000,data_tcon);
		#500
		data_tcon[6:2] = $random; 
		data_tcon = {1'b1,1'b0,data_tcon[5:1],1'b0};
		cpu.MOVT (4'b0000,data_tcon);
		int_tmr_cnt_we = 1'b1;
		int_tmr_cnt_wdata = 1'b0;	
		#100
		int_tmr_cnt_we = 1'b0;
		#2500
		data_sca[5:2] = 4'b0000;
		data_sca = {data_sca[5:2],2'b00};
		cpu.MOVT (4'b0001,data_sca);
		
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h);
		cpu.MOVT (4'b0010, 8'hfd);
		
	end
endtask
//count even

task tc17;
	begin
		data_tcon[5:2] = $random;
		data_sca[5:2] = 4'b0000;
		
		data_sca = {data_sca[5:2],2'b00};
		cpu.MOVT (4'b0001,data_sca);
		data_tcon = {1'b1,1'b0,data_tcon[5:2],2'b01};
		cpu.MOVT (4'b0000,data_tcon);
	end
endtask	

task tc18;
	begin
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h); 
		cpu.MOVT (4'b0010, data_init_l);
		tc17;
		#1500
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h); 
		cpu.MOVT (4'b0010, 8'hfa);
	end
endtask

task tc19;
	begin
		tc18;
		int_tmr_cnt_we = 1'b1;
		int_tmr_cnt_wdata = 1'b0;	
		#100
		int_tmr_cnt_we = 1'b0;
		#2500
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h);
		cpu.MOVT (4'b0010, 8'hfd);
		
	end
endtask
//count even
task tc20;
	begin
		tc19;
		int_tmr_cnt_we = 1'b1;
		int_tmr_cnt_wdata = 1'b0;	
		#100
		int_tmr_cnt_we = 1'b0;
		#2500
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h);
		cpu.MOVT (4'b0010, 8'hfd);
		
	end
endtask
//capture
task tc21; 
	begin
		tc18;
		data_tcon[5:2] = 4'b1_1_0_0; //enable, cạnh lên, 1:1
		data_sca[5:2] = 4'b0000;
		data_sca = {data_sca[5:2],2'b00};
		cpu.MOVT (4'b0001,data_sca);
		data_tcon = {1'b1,1'b0,data_tcon[5:2],2'b10};
		cpu.MOVT (4'b0000,data_tcon);
	end
endtask
task tc22; 
	begin
		tc18;
		data_tcon[5:2] = 4'b1_1_0_1; //enable, cạnh lên, 1:4
		data_sca[5:2] = 4'b0000;
		data_sca = {data_sca[5:2],2'b00};
		cpu.MOVT (4'b0001,data_sca);
		data_tcon = {1'b1,1'b0,data_tcon[5:2],2'b10};
		cpu.MOVT (4'b0000,data_tcon);
	end
endtask
//compare

task tc23; 
	begin
		//sca
		data_sca[5:2] = 4'b0000;
		data_sca = {data_sca[5:2],2'b00};
		cpu.MOVT (4'b0001,data_sca);
		//t3cnt
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h);
		cpu.MOVT (4'b0010, 8'hfd);
		//cmp
		cpu.MOVT (4'b0101, 8'b1111_1110); 
		cpu.MOVT (4'b0110, 8'b1111_1111); 
		cpu.MOVT (4'b0111, 8'b1111_1111); 
		//tcon
		data_tcon[5:2] = 4'b01_00; //enable, out = 1;
		data_tcon = {1'b1,1'b0,data_tcon[5:2],2'b10};
		cpu.MOVT (4'b0000,data_tcon);
		#1000
		data_sca = {data_sca[5:2],2'b01};
		cpu.MOVT (4'b0001,data_sca);
		
		cpu.MOVT (4'b0101, 8'b00011101); 
		cpu.MOVT (4'b0110, 8'b00000000); 
		cpu.MOVT (4'b0111, 8'b00000000); 
	end
endtask
task tc24; 
	begin
		//sca
		data_sca[5:2] = 4'b0000;
		data_sca = {data_sca[5:2],2'b00};
		cpu.MOVT (4'b0001,data_sca);
		//t3cnt
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h);
		cpu.MOVT (4'b0010, 8'hfd);
		//cmp
		cpu.MOVT (4'b0101, 8'b1111_1110); 
		cpu.MOVT (4'b0110, 8'b1111_1111); 
		cpu.MOVT (4'b0111, 8'b1111_1111); 
		//tcon
		data_tcon[5:2] = 4'b01_01; //enable, out = 0;
		data_tcon = {1'b1,1'b0,data_tcon[5:2],2'b10};
		cpu.MOVT (4'b0000,data_tcon);
		#1000
		data_sca = {data_sca[5:2],2'b01};
		cpu.MOVT (4'b0001,data_sca);
		
		cpu.MOVT (4'b0101, 8'b00011101); 
		cpu.MOVT (4'b0110, 8'b00000000); 
		cpu.MOVT (4'b0111, 8'b00000000); 
	end
endtask
task tc25; 
	begin
		//sca
		data_sca[5:2] = 4'b0000;
		data_sca = {data_sca[5:2],2'b00};
		cpu.MOVT (4'b0001,data_sca);
		//t3cnt
		cpu.MOVT (4'b0100, data_init_u);
		cpu.MOVT (4'b0011, data_init_h);
		cpu.MOVT (4'b0010, 8'hfd);
		//cmp
		cpu.MOVT (4'b0101, 8'b1111_1101); 
		cpu.MOVT (4'b0110, 8'b1111_1111); 
		cpu.MOVT (4'b0111, 8'b1111_1111); 
		//tcon
		data_tcon[5:2] = 4'b01_10; //enable, thay đổi;
		data_tcon = {1'b1,1'b0,data_tcon[5:2],2'b10};
		cpu.MOVT (4'b0000,data_tcon);
		#1000
		data_sca = {data_sca[5:2],2'b01};
		cpu.MOVT (4'b0001,data_sca);
		
		cpu.MOVT (4'b0101, 8'b00011101); 
		cpu.MOVT (4'b0110, 8'b00000000); 
		cpu.MOVT (4'b0111, 8'b00000000); 
	end
endtask
initial	begin
	$vcdplusfile ("wave.vpd");
	$vcdpluson ;
	end

initial begin
	#100000 $finish;
end
endmodule
